package api

import (
	"api-gateway/basic/inits"
	__ "api-gateway/basic/user_proto"
	"api-gateway/handler/request"
	"api-gateway/handler/response"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"log"
	"net/http"
	"strconv"
	"time"
)

// 站内信信息添加
func InfoAllSend(c *gin.Context) {
	var req request.InfoAllAddReq
	if err := c.ShouldBind(&req); err != nil {
		response.Error(c, 400, "参数错误", err.Error())
		return
	}

	res, err := inits.UserClient.InAppInfoAdd(c, &__.InAppInfoAddReq{
		UserId:   req.UserId,
		ToUserId: req.ToUserId,
		Title:    req.Title,
		Content:  req.Content,
		Types:    req.Types,
	})
	if err != nil {
		response.Error(c, 500, "信息添加失败", err.Error())
		return
	}
	response.Success(c, "信息添加成功", res.Id)
}

// 站内信信息列表
func InAppInfoList(c *gin.Context) {
	userId := c.GetUint("userId")
	res, err := inits.UserClient.InAppInfoList(c, &__.InAppInfoListReq{ToUserId: uint32(userId)})
	if err != nil {
		response.Error(c, 500, "信息查询失败", err.Error())
		return
	}
	response.Success(c, "信息查询成功", res)
}

// 站内信信息详情
func InAppInfoDetail(c *gin.Context) {
	var req request.GetCutGoodsId
	if err := c.ShouldBind(&req); err != nil {
		response.Error(c, 400, "参数错误", err.Error())
		return
	}
	res, err := inits.UserClient.InAppInfoDetail(c, &__.InAppInfoDetailReq{Id: uint32(req.Id)})
	if err != nil {
		response.Error(c, 500, "信息查询失败", err.Error())
		return
	}

	// 检查并更新消息的已读状态
	if res.IsRead == 1 {
		// 调用RPC将消息标记为已读
		_, err = inits.UserClient.UpdateInAppInfoUsRead(c, &__.UpdateInAppInfoUsReadReq{Id: res.Id})
		if err != nil {
			// 即使更新已读状态失败，也不影响返回消息详情
			fmt.Println("更新消息已读状态失败" + err.Error())
		} else {
			// 更新返回结果中的已读状态
			res.IsRead = 2
		}
	}
	response.Success(c, "信息查询成功", res)
}

type Node struct {
	Conn *websocket.Conn // Conn: WebSocket连接对象，用于与客户端进行双向通信
	Data chan []byte     // Data: 用于接收和发送数据的通道，存储字节切片
}

// OnlineUser 存储在线用户映射表
// 用于维护当前所有在线用户的连接状态
var OnlineUser = make(map[uint]*websocket.Conn)

type WSResp struct {
	Code uint        `json:"code"` // Code: 状态码，0表示成功，非0表示失败
	Msg  string      `json:"msg"`  // Msg: 响应消息，通常包含错误信息或成功提示
	Data interface{} `json:"data"` // Data: 响应数据，可以是任意类型的具体业务数据
}

type SendS struct {
	ToUserId uint   `json:"to_user_id"` // ToUserId: 目标用户的ID
	Title    string `json:"title"`      // Title: 消息标题
	Content  string `json:"content"`    // Content: 消息内容
	Types    int    `json:"types"`      // Types: 消息类型标识
}

func Chat(c *gin.Context) {
	userIdStr, _ := c.GetQuery("userId")
	var userId int
	userId, _ = strconv.Atoi(userIdStr)

	//	userId := c.GetUint("userId")

	// 初始化 WebSocket 升级器，允许所有来源的连接
	var upgrader = websocket.Upgrader{
		CheckOrigin: func(r *http.Request) bool {
			return true // 任何来源都允许
		},
	}
	// 将当前 HTTP 连接升级为 WebSocket 连接
	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		log.Print("upgrade:", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "websocket fail",
			"data": nil,
		})
		return
	}

	defer conn.Close()
	// 启动一个goroutine定期向WebSocket连接发送ping消息
	// 用于保持连接活跃状态，检测连接是否断开
	go func() {
		// 30s
		for {
			err = conn.WriteMessage(websocket.PingMessage, []byte{})
			if err != nil {
				return
			}
			// 间隔30秒
			time.Sleep(30 * time.Second)
		}
	}()

	// 将当前用户加入在线用户映射表
	OnlineUser[uint(userId)] = conn
	log.Println(OnlineUser)
	for {
		// 读取客户端发送的消息
		_, message, err := conn.ReadMessage()
		if err != nil {
			log.Println("read:", err)
			break
		}

		var req SendS
		// 解析接收到的 JSON 数据
		err = json.Unmarshal(message, &req)
		if err != nil {

			WSRespErr(conn, 1000, "illegal json")
			continue
		}
		// 消息入库
		_, err = inits.UserClient.InAppInfoAdd(c, &__.InAppInfoAddReq{
			UserId:   uint32(userId),
			ToUserId: uint32(req.ToUserId),
			Title:    req.Title,
			Content:  req.Content,
			Types:    int64(req.Types),
		})
		if err != nil {
			c.JSON(http.StatusOK, gin.H{
				"code": -1,
				"msg":  "消息入库失败" + err.Error(),
				"data": nil,
			})
			return
		}
		// 根据消息类型选择不同的发送方式
		switch req.Types {
		case 1:
			go Send(conn, message, uint(userId))
		case 2:
			go SendGroup(conn, message, uint(userId))
		default:
			WSRespErr(conn, 10001, "no function")
		}

	}
}

func SendGroup(conn *websocket.Conn, message []byte, userId uint) {
	var req SendS
	err := json.Unmarshal(message, &req)
	if err != nil {
		WSRespErr(conn, 20001, "Parsing json failed ")
		return
	}
	// 验证消息参数是否完整
	if req.Title == "" || req.Content == "" {
		WSRespErr(conn, 20004, "not Message params")
		return
	}
	// 检查是否有在线用户
	if len(OnlineUser) == 0 {
		WSRespErr(conn, 20002, "not Online user")
		return
	}
	// 向所有在线用户发送消息
	for _, onlineConn := range OnlineUser {

		WSRespSuccess(onlineConn, req)

	}
}

func Send(conn *websocket.Conn, message []byte, userId uint) {
	var req SendS
	err := json.Unmarshal(message, &req)
	if err != nil {
		WSRespErr(conn, 20001, "Parsing json failed ")
		return
	}
	if req.ToUserId < 1 {
		WSRespErr(conn, 20002, "not ToUserId params")
		return
	}
	if req.Title == "" || req.Content == "" {
		WSRespErr(conn, 20004, "not Message params")
		return
	}

	if OnlineUser[req.ToUserId] == nil {
		WSRespErr(conn, 20003, "not online")
		return
	}

	WSRespSuccess(OnlineUser[req.ToUserId], req)

	WSRespSuccess(conn, "send ok")

}

func WSRespErr(conn *websocket.Conn, code uint, msg string) {
	responses := WSResp{
		Code: code,
		Msg:  msg,
		Data: nil,
	}

	responseStr, _ := json.Marshal(responses)

	err := conn.WriteMessage(websocket.TextMessage, responseStr)
	if err != nil {
		log.Println("write:", err)
	}
}

func WSRespSuccess(conn *websocket.Conn, data interface{}) {
	responses := WSResp{
		Code: http.StatusOK,
		Msg:  "ok",
		Data: data,
	}

	responseStr, _ := json.Marshal(responses)

	err := conn.WriteMessage(websocket.TextMessage, responseStr)
	if err != nil {
		log.Println("write:", err)
	}
}
